package com.zhongkun.datahome.service.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zhongkun.datahome.common.exception.ServiceException;
import com.zhongkun.datahome.common.utils.SecurityUtils;
import com.zhongkun.datahome.common.utils.bean.BeanConverter;
import com.zhongkun.datahome.core.repository.TenantUserRepository;
import com.zhongkun.datahome.service.constant.EntityTypeEnum;
import com.zhongkun.datahome.service.constant.TaskStatusEnum;
import com.zhongkun.datahome.service.constant.TaskTypeEnum;
import com.zhongkun.datahome.service.domain.CommonFile;
import com.zhongkun.datahome.service.domain.CustomerBase;
import com.zhongkun.datahome.service.domain.Task;
import com.zhongkun.datahome.service.domain.TaskNoticeFamily;
import com.zhongkun.datahome.service.domain.TaskProgress;
import com.zhongkun.datahome.service.repository.CommonFileRepository;
import com.zhongkun.datahome.service.repository.CustomerBaseRepository;
import com.zhongkun.datahome.service.repository.CustomerHouseRepository;
import com.zhongkun.datahome.service.repository.TaskNoticeFamilyRepository;
import com.zhongkun.datahome.service.repository.TaskProgressRepository;
import com.zhongkun.datahome.service.repository.TaskRepository;
import com.zhongkun.datahome.service.req.cmd.task.TaskCmd;
import com.zhongkun.datahome.service.req.cmd.task.TaskProcessCmd;
import com.zhongkun.datahome.service.req.qry.task.TaskQry;
import com.zhongkun.datahome.service.res.CommonFileVo;
import com.zhongkun.datahome.service.res.PageVo;
import com.zhongkun.datahome.service.res.house.CustomerHouseVo;
import com.zhongkun.datahome.service.res.task.MyTaskVo;
import com.zhongkun.datahome.service.res.task.TaskProgressVo;
import com.zhongkun.datahome.service.res.task.TaskVo;
import com.zhongkun.datahome.service.service.ITaskService;
import com.zhongkun.datahome.service.utils.StreamUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
public class TaskServiceImpl implements ITaskService {

    @Autowired
    private TaskRepository taskRepository;

    @Autowired
    private TaskProgressRepository taskProgressRepository;

    @Autowired
    private CommonFileRepository commonFileRepository;

    @Autowired
    private TenantUserRepository tenantUserRepository;

    @Autowired
    private TaskNoticeFamilyRepository taskNoticeFamilyRepository;

    @Autowired
    private CustomerBaseRepository customerBaseRepository;

    @Resource
    private CustomerHouseRepository customerHouseRepository;


    @Override
    public PageVo<TaskVo> page(TaskQry qry) {

        IPage<Task> taskPage = taskRepository.pageTask(qry);
        List<Task> taskList = taskPage.getRecords();
        List<TaskVo> taskVoList = BeanConverter.convertList(taskList, TaskVo.class);

        updateTaskUserName(taskVoList);
        addFeedbackTaskStarterHouseInfo(taskVoList);
        return new PageVo<>(taskVoList, qry.getPageNo(), qry.getPageSize(), taskPage.getTotal());
    }

    private void addFeedbackTaskStarterHouseInfo(List<TaskVo> taskVoList) {
        List<TaskVo> feedBackTasks = taskVoList.stream()
                .filter(item -> TaskTypeEnum.FEEDBACK.is(item.getTaskType()))
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(feedBackTasks)) {
            return;
        }

        // 发起业主userTenantIds
        List<Long> startTenantUserIds = feedBackTasks.stream().map(TaskVo::getStartTenantUserId).collect(Collectors.toList());

        Map<Long, String> houseInfoMap = customerHouseRepository.getBaseMapper()
                .listByTenantUserIds(startTenantUserIds)
                .stream().collect(Collectors.groupingBy(CustomerHouseVo::getCustomerTenantUserId,
                        Collectors.mapping(CustomerHouseVo::ofHouseInfo, Collectors.joining(","))));

        feedBackTasks.forEach(item -> {
            if (houseInfoMap.containsKey(item.getStartTenantUserId())) {
                item.setStartUserName(String.format("%s（%s）", item.getStartUserName(), houseInfoMap.get(item.getStartTenantUserId())));
            }
        });

        if (CollectionUtils.isNotEmpty(taskVoList)) {
            List<TaskVo> feedBackList = taskVoList.stream().filter(item -> Objects.isNull(item.getReceiveTenantUserId()) || item.getReceiveTenantUserId() == 0L)
                    .filter(item -> TaskTypeEnum.FEEDBACK.is(item.getTaskType()))
                    .collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(feedBackList)) {
                List<String> processUserList = taskRepository.queryFeedbackProcessUser();
                feedBackList.forEach(item -> item.setReceiveUserName(String.join(",", processUserList)));
            }
        }

    }

    private void updateTaskUserName(List<TaskVo> taskVoList) {
        tenantUserRepository.batchSetUserName(taskVoList, TaskVo::getStartTenantUserId, TaskVo::setStartUserName);
        tenantUserRepository.batchSetUserName(taskVoList, TaskVo::getReceiveTenantUserId, TaskVo::setReceiveUserName);
    }

    @Override
    public TaskVo getInfo(Long id) {
        TaskVo taskVo = BeanConverter.copyBean(TaskVo.class, taskRepository.getById(id));
        updateTaskUserName(List.of(taskVo));
        addFeedbackTaskStarterHouseInfo(List.of(taskVo));

        List<CommonFile> commonFileList = commonFileRepository.listByDataAssetsIds(List.of(String.valueOf(id)), EntityTypeEnum.TASK);
        List<CommonFileVo> commonFileVoList = BeanConverter.convertList(commonFileList, CommonFileVo.class);
        taskVo.setFileVoList(commonFileVoList);

        List<TaskProgress> taskProgressList = taskProgressRepository.listByTaskId(id);
        List<TaskProgressVo> taskProgressVoList = BeanConverter.convertList(taskProgressList, TaskProgressVo.class);

        if (TaskStatusEnum.PROCESSING.getType().equals(taskVo.getTaskStatus())) {
            TaskProgressVo taskProgressVo = new TaskProgressVo();
            taskProgressVo.setExpectFinishTime(taskVo.getExpectFinishTime());
            taskProgressVo.setProcessStatus(TaskStatusEnum.PROCESSING.getType());
            taskProgressVo.setProcessUserName(taskVo.getReceiveUserName());
            // 第一个处理才露出问题反馈处理角色的人
            if (TaskTypeEnum.FEEDBACK.is(taskVo.getTaskType()) && taskProgressVoList.size() == 1) {
                List<String> processUserList = taskRepository.queryFeedbackProcessUser();
                taskProgressVo.setProcessUserName(String.join(",", processUserList));
            }
            taskProgressVoList.add(taskProgressVo);
        }

        List<String> progressIdList = taskProgressVoList.stream().map(TaskProgress::getId).map(String::valueOf).collect(Collectors.toList());
        List<CommonFile> progressFileList = commonFileRepository.listByDataAssetsIds(progressIdList, EntityTypeEnum.TASK_PROGRESS);
        Map<String, List<CommonFile>> CommonFileMap = StreamUtil.listGroupBy(progressFileList, CommonFile::getEntityId);

        for (TaskProgressVo taskProgressVo : taskProgressVoList) {
            taskProgressVo.setFileVoList(BeanConverter.convertList(CommonFileMap.get(String.valueOf(taskProgressVo.getId())), CommonFileVo.class));
        }
        taskVo.setTaskProgressVoList(taskProgressVoList);


        return taskVo;
    }

    @Override
    @Transactional
    public Long add(TaskCmd cmd) {
        Task task = BeanConverter.copyBean(Task.class, cmd);
        task.setStartTenantUserId(SecurityUtils.getTenantUserId());
        if (TaskTypeEnum.NOTICE.getType().equals(cmd.getTaskType())) {
            task.setTaskStatus(TaskStatusEnum.FINISH.getType());
        } else {
            task.setTaskStatus(TaskStatusEnum.PROCESSING.getType());
        }

        if (CollectionUtils.isNotEmpty(cmd.getHouseList())) {
            task.setHouseInfo(String.join(",", cmd.getHouseList()));
        }
        taskRepository.save(task);

        // 通知任务需要关联家庭
        if (CollectionUtils.isNotEmpty(cmd.getFamilyIdList())) {
            List<Long> familyIdList = cmd.getFamilyIdList().stream().distinct().collect(Collectors.toList());
            List<TaskNoticeFamily> taskNoticeFamilyList = new ArrayList<>();
            for (Long familyId : familyIdList) {
                taskNoticeFamilyList.add(new TaskNoticeFamily(task.getId(), familyId));
            }
            taskNoticeFamilyRepository.saveBatch(taskNoticeFamilyList);
        }

        if (!TaskTypeEnum.NOTICE.getType().equals(cmd.getTaskType())) {
            TaskProgress taskProgress = new TaskProgress();
            taskProgress.setTaskId(task.getId());
            taskProgress.setExpectFinishTime(cmd.getExpectFinishTime());
            taskProgress.setTaskSuggestion("创建任务");
            taskProgress.setProcessUserName(SecurityUtils.getUsername());
            if (TaskTypeEnum.FEEDBACK.is(cmd.getTaskType())) {
                Map<Long, String> houseInfoMap = customerHouseRepository.getBaseMapper()
                        .listByTenantUserIds(List.of(SecurityUtils.getTenantUserId()))
                        .stream().collect(Collectors.groupingBy(CustomerHouseVo::getCustomerTenantUserId,
                                Collectors.mapping(CustomerHouseVo::ofHouseInfo, Collectors.joining(","))));
                taskProgress.setProcessUserName(String.format("%s（%s）", taskProgress.getProcessUserName(), houseInfoMap.get(SecurityUtils.getTenantUserId())));
            }
            taskProgressRepository.save(taskProgress);
        }

        if (CollectionUtils.isNotEmpty(cmd.getCommonFileCmdList())) {
            List<CommonFile> commonFileList = CommonFile.convertTaskFile(task.getId(), cmd.getCommonFileCmdList(), EntityTypeEnum.TASK);
            commonFileRepository.saveBatch(commonFileList);
        }

        return task.getId();
    }

    @Override
    @Transactional
    public void remove(Long id) {
        taskRepository.removeById(id);
        taskProgressRepository.removeByTaskId(id);
    }

    @Override
    public Long process(TaskProcessCmd cmd) {
        Task task = taskRepository.getById(cmd.getTaskId());
        if (TaskStatusEnum.FINISH.getType().equals(task.getTaskStatus())) {
            throw new ServiceException("任务已经完成,无法继续处理");
        }
        Long originalReceiveId = task.getReceiveTenantUserId();

        if (cmd.isEnd()) {
            task.setFinishTime(new Date());
            task.setTaskStatus(TaskStatusEnum.FINISH.getType());
        } else {
            task.setReceiveTenantUserId(cmd.getReceiveUserId());
            task.setExpectFinishTime(cmd.getExpectFinishTime());
            task.setReceiveTenantUserId(cmd.getReceiveUserId());
        }
        taskRepository.updateById(task);

        TaskProgress taskProgress = BeanConverter.copyBean(TaskProgress.class, cmd);
        // 处理人为null， 非问题反馈角色， 处理人不是当前操作人
        if (((originalReceiveId == null || originalReceiveId == 0L) && !taskRepository.isTaskRoleUser(SecurityUtils.getTenantUserId())) || (!Objects.equals(originalReceiveId, SecurityUtils.getTenantUserId()))) {
            taskProgress.setTaskSuggestion(taskProgress.getTaskSuggestion() + MessageFormat.format("({0}代处理)", SecurityUtils.getLoginUser().getUser().getNickName()));
        }
        if ((originalReceiveId == null || originalReceiveId == 0L)) {
            taskProgress.setProcessUserName(String.join(",", taskRepository.queryFeedbackProcessUser()));
        } else {
            taskProgress.setProcessUserName(tenantUserRepository.getUserName(originalReceiveId));
        }
        log.info("原处理人:{}", taskProgress.getProcessUserName());
        taskProgressRepository.save(taskProgress);
        if (CollectionUtils.isNotEmpty(cmd.getCommonFileCmdList())) {
            List<CommonFile> commonFileList = CommonFile.convertTaskFile(taskProgress.getId(), cmd.getCommonFileCmdList(), EntityTypeEnum.TASK_PROGRESS);
            commonFileRepository.saveBatch(commonFileList);
        }

        return taskProgress.getId();
    }

    @Override
    public MyTaskVo myTask(Long tenantUserId, boolean employeeFlag) {
        MyTaskVo myTaskVo = new MyTaskVo();
        // 接收任务类型
        List<String> receiveTaskTypes = TaskTypeEnum.getReceiveTaskType(employeeFlag);
        // 发起任务类型
        List<String> startTaskTypes = TaskTypeEnum.getStartTaskType(employeeFlag);

        CustomerBase customerBase = customerBaseRepository.getByTenantUserId(tenantUserId);
        List<Task> receiveTaskList = taskRepository.queryReceiveTaskList(tenantUserId, customerBase == null ? null : customerBase.getFamilyId())
                .stream()
                .filter(task -> receiveTaskTypes.contains(task.getTaskType()))
                .collect(Collectors.toList());
        myTaskVo.setMyReceiveTaskList(BeanConverter.convertList(receiveTaskList, TaskVo.class));

        List<Task> startTaskList = taskRepository.queryStartTaskList(tenantUserId)
                .stream()
                .filter(task -> startTaskTypes.contains(task.getTaskType()))
                .collect(Collectors.toList());
        myTaskVo.setMyStartTaskList(BeanConverter.convertList(startTaskList, TaskVo.class));

        updateTaskUserName(myTaskVo.getMyReceiveTaskList());
        updateTaskUserName(myTaskVo.getMyStartTaskList());
        addFeedbackTaskStarterHouseInfo(myTaskVo.getMyReceiveTaskList());
        return myTaskVo;
    }

    @Override
    public Long queryReceiveTaskCount(Long tenantUserId) {
        return taskRepository.queryReceiveTaskCount(tenantUserId);
    }
}